package com.dge.common.utils

import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.ExifInterface
import android.net.Uri
import android.os.Build
import android.os.ParcelFileDescriptor
import android.provider.MediaStore
import androidx.core.content.FileProvider
import androidx.core.net.toUri
import com.blankj.utilcode.util.ScreenUtils
import com.dge.common.LibApp
import com.dge.common.common.Constants
import com.dge.common.extentions.dp
import timber.log.Timber
import java.io.File
import java.io.FileDescriptor
import java.io.IOException
import java.io.InputStream
import kotlin.math.roundToInt

object ImageUtils {
    private const val TAG = "ImageUtils"
    const val INTENT_KEY_FILE_SCHEME_FILE_URI = "intent_key_file_scheme_file_uri"

    /**
     *      * 图片裁剪
     *
     * @param uri
     * @param aspectX x方向上比例
     * @param aspectY Y方向上比例
     * @return
     */
    fun cutForPhoto(uri: Uri, aspectX: Int, aspectY: Int, hasFixedRate: Boolean): Intent? {
        try {
            val folder = File(FileUtil.APP_CAMERA_PATH)
            if (!folder.exists()) folder.mkdirs()
            //直接裁剪
            val intent = Intent("com.android.camera.action.CROP")
            //设置裁剪之后的图片路径文件
            val cutfile = File(
                FileUtil.APP_CAMERA_PATH,
                "${System.currentTimeMillis()}.jpg"
            ) //随便命名一个
            if (cutfile.exists()) { //如果已经存在，则先删除,这里应该是上传到服务器，然后再删除本地的，没服务器，只能这样了
                cutfile.delete()
            }
            cutfile.createNewFile()
            //初始化 uri
            var outputUri: Uri?  //真实的 uri
            Timber.d("CutForPhoto: $cutfile")
            outputUri = Uri.fromFile(cutfile)
            Timber.d("outputUri: $outputUri")
            // crop为true是设置在开启的intent中设置显示的view可以剪裁
            intent.putExtra("crop", true)
            if (hasFixedRate) {
                intent.putExtra("aspectX", aspectX)
                intent.putExtra("aspectY", aspectY)
            }
            val bitmap = getBitmapFromUri(uri)
            Timber.d("cutForPhoto ${bitmap?.width},${bitmap?.height}")
            val outputX = ScreenUtils.getScreenWidth()
            //设置要裁剪的宽高
            if (bitmap == null) {
                intent.putExtra("outputX", outputX)
                intent.putExtra("outputY", (outputX * 1.0f * aspectY / aspectX).toInt())
            } else {
                if (bitmap.width >= bitmap.height) {
                    intent.putExtra("outputX", outputX)
                    intent.putExtra("outputY", (outputX * 1.0f * aspectY / aspectX).toInt())
                } else {
                    intent.putExtra("outputX", (outputX * 1.0f * aspectY / aspectX).toInt())
                    intent.putExtra("outputY", outputX)
                }
            }
            intent.putExtra("scale", true)
            intent.putExtra("scaleUpIfNeeded", true)//去黑边
            //如果图片过大，会导致oom，这里设置为false
            intent.putExtra("return-data", false)
            intent.setDataAndType(uri, "image/*")
            if (outputUri != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri)
            }
            intent.putExtra("noFaceDetection", true)
            //压缩图片
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString())
            return intent
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 图片裁剪
     *
     * @param uri
     * @return
     */
    fun cutForPhoto(uri: Uri): Intent? {
        return cutForPhoto(uri, 1, 1, true)
    }

    /**
     * 拍照之后，启动裁剪
     * @param aspectX x方向上比例
     * @param aspectY Y方向上比例
     * @return
     */
    fun cutForCamera(aspectX: Int, aspectY: Int, filePath: String, hasFixedRate: Boolean): Intent? {
        try {
            val context: Context = LibApp.context
            val folder = File(FileUtil.APP_CAMERA_PATH)
            if (!folder.exists()) folder.mkdirs()
            val cutfile = File(
                FileUtil.APP_CAMERA_PATH,
                "${System.currentTimeMillis()}.jpg"
            ) //随便命名一个
            if (cutfile.exists()) {
                cutfile.delete()
            }
            cutfile.createNewFile()
            //初始化 uri
            var imageUri: Uri? //返回来的 uri
            val intent = Intent("com.android.camera.action.CROP")
            //拍照留下的图片
            val camerafile = File(filePath)
            imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                FileProvider.getUriForFile(
                    context,
                    Constants.fileProviderAuthority,
                    camerafile
                )
            } else {
                Uri.fromFile(camerafile)
            }
            //把这个 uri 提供出去，就可以解析成 bitmap了
            var outputUri: Uri? = Uri.fromFile(cutfile) //真实的 uri
            // crop为true是设置在开启的intent中设置显示的view可以剪裁
            intent.putExtra("crop", true)
            if (hasFixedRate) {
                // aspectX,aspectY 是宽高的比例
                intent.putExtra("aspectX", aspectX)
                intent.putExtra("aspectY", aspectY)
            }
            val bitmap = getBitmapFromUri(camerafile.toUri())
            Timber.d("cutForPhoto ${bitmap?.width},${bitmap?.height}")
            val outputX = ScreenUtils.getScreenWidth()
            //设置要裁剪的宽高
            if (bitmap == null) {
                intent.putExtra("outputX", outputX)
                intent.putExtra("outputY", (outputX * 1.0f * aspectY / aspectX).toInt())
            } else {
                if (bitmap.width >= bitmap.height) {
                    intent.putExtra("outputX", outputX)
                    intent.putExtra("outputY", (outputX * 1.0f * aspectY / aspectX).toInt())
                } else {
                    intent.putExtra("outputX", (outputX * 1.0f * aspectY / aspectX).toInt())
                    intent.putExtra("outputY", outputX)
                }
            }
            intent.putExtra("scale", true)//去黑边
            intent.putExtra("scaleUpIfNeeded", true)//去黑边
            //如果图片过大，会导致oom，这里设置为false
            intent.putExtra("return-data", false)
            if (imageUri != null) {
                intent.setDataAndType(imageUri, "image/*")
            }
            if (outputUri != null) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri)
            }
            intent.putExtra("noFaceDetection", true)
            //压缩图片
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString())
            return intent
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 拍照之后，启动裁剪
     *
     * @return
     */
    fun cutForCamera(filepath: String): Intent? {
        return cutForCamera(1, 1, filepath, true);
    }

    /**
     * 获取打开相机Intent
     */
    fun getCameraIntent(): Intent {
        val context: Context = LibApp.context
        //创建一个file，用来存储拍照后的照片
        val folder = File(FileUtil.APP_CAMERA_PATH)
        if (!folder.exists()) folder.mkdirs()
        val outputfile =
            File(FileUtil.APP_CAMERA_PATH, "${System.currentTimeMillis()}.png")
        Timber.d("getCameraIntent outputfile.path = " + outputfile.absolutePath)
        try {
            if (outputfile.exists()) {
                outputfile.delete() //删除
            }
            outputfile.createNewFile()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val imageUri: Uri
        val fileContentUri = Uri.fromFile(outputfile)
        imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            FileProvider.getUriForFile(
                context,
                Constants.fileProviderAuthority,
                outputfile
            )
        } else {
            fileContentUri
        }
        //启动相机程序
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
        intent.putExtra(INTENT_KEY_FILE_SCHEME_FILE_URI, fileContentUri.toString())
        return intent
    }

    fun getExifOrientation(uri: Uri): Int {
        var degree = 0
        var exif: ExifInterface? = null
        var inputStream: InputStream? = null
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                inputStream = LibApp.context.contentResolver.openInputStream(uri)
                if (inputStream != null)
                    exif = ExifInterface(inputStream)
            } else if ("file".contentEquals(uri.scheme!!)) {
                exif = ExifInterface(uri.path!!)
            }
        } catch (ex: IOException) {
            Timber.d("cannot read exif$ex")
        } finally {
            try {
                inputStream?.close()
            } catch (e: java.lang.Exception) {
            }
        }

        if (exif != null) {
            val orientation: Int = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)
            Timber.d("getExifOrientation orientation = $orientation")
            if (orientation != -1) {
                when (orientation) {
                    ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
                    ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
                    ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
                }
            }
        } else {
            Timber.d("getExifOrientation exif == null")
        }
        return degree
    }

    fun getBitmapFromUri(uri: Uri): Bitmap? {
        Timber.d("getBitmapFromUri uri.scheme = ${uri.scheme} uri = $uri")
        if ("file" == uri.scheme || uri.toString().startsWith("file://"))
            return BitmapFactory.decodeFile(uri.path)
        else
            try {
                val parcelFileDescriptor: ParcelFileDescriptor =
                    LibApp.context.contentResolver.openFileDescriptor(uri, "r")!!
                val fileDescriptor: FileDescriptor = parcelFileDescriptor.fileDescriptor
                val image: Bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
                parcelFileDescriptor.close()

                return image
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        return null
    }

    /**
     * 根据传入的宽和高，计算出合适的 inSampleSize 值
     */
    fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int, reqHeight: Int
    ): Int {
        //  源图片的高度和宽度
        val tHeight = options.outHeight
        val tWidth = options.outWidth
        var tInSampleSize = 1
        if (tHeight > reqHeight || tWidth > reqWidth) {
            //  计算出实际宽高和目标宽高的比率
            val tHeightRatio = (tHeight.toFloat()
                    / reqHeight.toFloat()).roundToInt()
            val tWidthRatio = (tWidth.toFloat()
                    / reqWidth.toFloat()).roundToInt()
            /*
             * 选择宽和高中最小的比率作为inSampleSize的值， 这样可以保证最终图片的宽和高，一定都会
             * 大于等于目标的宽和高。
             */

            tInSampleSize = if (tHeightRatio < tWidthRatio) tHeightRatio else tWidthRatio
        }
        return tInSampleSize
    }

    /**
     * 根据传入的宽和高，生成相应大小的缩略图
     *
     * @param res
     * @param resId
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    fun decodeSampledBitmapFromResource(
        res: Resources?,
        resId: Int, reqWidth: Int, reqHeight: Int
    ): Bitmap? {
        // 第一次解析将inJustDecodeBounds设置为true，来获取图片大小
        val tOptions = BitmapFactory.Options()
        tOptions.inJustDecodeBounds = true
        BitmapFactory.decodeResource(res, resId, tOptions)
        // 调用上面定义的方法计算inSampleSize值
        tOptions.inSampleSize = calculateInSampleSize(
            tOptions, reqWidth,
            reqHeight
        )
        // 使用获取到的inSampleSize值再次解析图片
        tOptions.inJustDecodeBounds = false
        return BitmapFactory.decodeResource(res, resId, tOptions)
    }

    fun getFileBitmap(imagePath: String?): Bitmap {
        // 第一次解析将inJustDecodeBounds设置为true，来获取图片大小
        val tOptions = BitmapFactory.Options()
        tOptions.inJustDecodeBounds = true;//测量image 不加载到内存
        BitmapFactory.decodeFile(imagePath, tOptions)
        var reqWidth: Int
        var reqHeight: Int
        val width: Int = tOptions.outWidth
        val height: Int = tOptions.outHeight
        Timber.d("width = $width; height = $height")
        if (width > height) {
            reqWidth = 150.dp
            reqHeight = reqWidth * height / width
        } else {
            reqHeight = 150.dp
            reqWidth = width * reqHeight / height
        }
        // 调用上面定义的方法计算inSampleSize值
        tOptions.inSampleSize = calculateInSampleSize(tOptions, reqWidth, reqHeight)
        // 使用获取到的inSampleSize值再次解析图片
        tOptions.inJustDecodeBounds = false
        return BitmapFactory.decodeFile(imagePath, tOptions)
    }
}